package com.founder.gateway.component.transport.netty.extension.support;

import static com.founder.gateway.system.util.HttpNormUtil.APPEND_UTF_8;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

import org.setu.framework.thread.SetuThreadLocalHandler;
import org.setu.framework.thread.offline.task.SetuOffLineThreadTaskHandler;

import com.founder.gateway.component.transport.netty.exception.NettyException;
import com.founder.gateway.component.transport.netty.filter.NettyFilterChain;
import com.founder.gateway.component.transport.netty.http.NettyHttpRequest;
import com.founder.gateway.component.transport.netty.http.NettyHttpResponse;
import com.founder.gateway.system.bean.SetuResult;

import io.netty.handler.codec.http.HttpHeaderNames;
import io.netty.handler.codec.http.HttpHeaderValues;
import io.netty.handler.codec.http.QueryStringDecoder;
import io.netty.handler.codec.http.multipart.Attribute;
import io.netty.handler.codec.http.multipart.HttpPostRequestDecoder;
import io.netty.handler.codec.http.multipart.InterfaceHttpData;

public class BaseNettyHttpFilter extends AbstractNettyHttpFilter {

    @Override
    public void doFilter(NettyHttpRequest request, NettyHttpResponse response, NettyFilterChain chain)
            throws IOException, NettyException {
        SetuResult result = null;
        long startTime = System.currentTimeMillis();
        Exception exception = null;
        try {
            QueryStringDecoder paramDecoder = new QueryStringDecoder(request.uri());
            for (Map.Entry<String, List<String>> entry : paramDecoder.parameters().entrySet()) {
                for (String value : entry.getValue()) {
                    request.getParameterMap().getParam().computeIfAbsent(entry.getKey(), k ->
                            new ArrayList<>()).add(value);
                }
            }
            request.setAction(paramDecoder.path());
            HttpPostRequestDecoder bodyDecoder = new HttpPostRequestDecoder(request);
            List<InterfaceHttpData> list = bodyDecoder.getBodyHttpDatas();
            if (!list.isEmpty()) {
                for (InterfaceHttpData data : bodyDecoder.getBodyHttpDatas()) {
                    if (data.getHttpDataType() == InterfaceHttpData.HttpDataType.Attribute) {
                        Attribute attribute = (Attribute) data;
                        request.getParameterMap().getBody().computeIfAbsent(attribute.getName(), k ->
                                new ArrayList<>()).add(attribute.getValue());
                    }
                }
            }
            for (Map.Entry<String, List<String>> entry : request.getParameterMap().getMaps().entrySet()) {
                String key = entry.getKey();
                List<String> value = entry.getValue();
                if (value != null && !value.isEmpty()) {
                    SetuThreadLocalHandler.getRequestParams().put(key, value.toArray(new String[0]));
                }
            }
            chain.doFilter(request, response);
            result = response.getSetuResult();
        } catch (Exception e) {
            exception = e;
            result = new SetuResult();
            result.setCode(500);
            result.setMsg(e.getMessage());
        } finally {
            long endTime = System.currentTimeMillis();
            byte[] content = null;
            if (result == null) {
                content = response.getContent();
                if (content == null || content.length == 0) {
                    result = new SetuResult(500, "content empty");
                }
            }
            if (result != null) {
                content = result.toString().getBytes();
                response.headers().set(HttpHeaderNames.CONTENT_TYPE, HttpHeaderValues.APPLICATION_JSON + APPEND_UTF_8);
            }

            response.content().writeBytes(content);
            SetuOffLineThreadTaskHandler.exec(request.getAction(), content, startTime, endTime, exception);
        }
    }
}
